using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace TodoistClient
{
    public class TaskItem
    {
        public TaskItem()
        {
        }
        private DateTime _dueDate;

        public DateTime DueDate
        {
            get { return _dueDate; }
            set { _dueDate = value; }
        }
        private int _priority;

        public int Priority
        {
            get { return _priority; }
            set { _priority = value; }
        }
        private string _content;

        public string Content
        {
            get { return _content; }
            set { _content = value; }
        }
        private long _id;

        public long ID
        {
            get { return _id; }
            set { _id = value; }
        }
        private bool _checked;

        public bool Checked
        {
            get { return _checked; }
            set { _checked = value; }
        }
        private DateTime _date;

        public DateTime Date
        {
            get { return _date; }
            set { _date = value; }
        }

        private bool _completed=false;

        public bool Completed
        {
            get { return _completed; }
            set { _completed = value; }
        }


    }
    public class Project
    {
        private string _name;
        private Color _color;
        private long _id;
        private List<TaskItem> __items = new List<TaskItem>();

        public Project()
        {
        }
        public Project(string name, Color color)
        {
            _name = name;
            _color = color;
        }

        private int _userID;

        public int UserID
        {
            get { return _userID; }
            set { _userID = value; }
        }
        private bool _collapsed;

        public bool Collapsed
        {
            get { return _collapsed; }
            set { _collapsed = value; }
        }
        private int _order;

        public int Order
        {
            get { return _order; }
            set { _order = value; }
        }
        private int _indend;

        public int Indent
        {
            get { return _indend; }
            set { _indend = value; }
        }
        private int _cacheCount;

        public int CacheCount
        {
            get { return _cacheCount; }
            set { _cacheCount = value; }
        }


        public List<TaskItem> Items
        {
            get { return __items; }
            set { __items = value; }
        }        

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        
        public Color Color
        {
            get { return _color; }
            set { _color = value; }
        }

        public long ID
        {
            get { return _id; }
            set { _id = value; }
        }

    }
    class TodoIstEngine
    {
        private List<Project> _projects=new List<Project>();

        public List<Project> Projects
        {
            get { return _projects; }
            set { _projects = value; }
        }

        static string todobaseurl = "http://todoist.com/API/";
        static string getallprojects= "getProjects?token=[TOKEN]";
        static string getuncompleteditems = "getUncompletedItems?project_id=[PROJID]&token=[TOKEN]";
        static string getcompleteditems = "getCompletedItems?project_id=[PROJID]&token=[TOKEN]";
        static string additem = "addItem?content=[CONTENT]&project_id=[PROJID]&priority=[PRIORITY]&token=[TOKEN]";
        static string updateitem = "updateItem?id=[ID]&content=[CONTENT]&token=[TOKEN]";
        static string updatecompleted = "completeItems?ids=[[IDS]]&token=[TOKEN]";
        static string deleteitem = "deleteItems?id=[ID]&token=[TOKEN]";
        
        public void RefreshDataFromService()
        {
            try
            {
                _projects = new List<Project>();
                _projects = GetProjects();
                foreach (Project __proj in _projects)
                {
                    __proj.Items.AddRange(GetUncompletedItems(__proj.ID));
                    __proj.Items.AddRange(GetCompletedItems(__proj.ID));
                }
            }
            catch (Exception err)
            {
                ErrorHandler.HandleError("Error Occurred In RefreshFromService", err);
            }
        }

        public string password="";

        private string GetWebData(Uri url)
        {
            try
            {
                // used to build entire input
                StringBuilder sb = new StringBuilder();

                // used on each read operation
                byte[] buf = new byte[8192];

                // prepare the web page we will be asking for
                HttpWebRequest request = (HttpWebRequest)
                    WebRequest.Create(url);

                // execute the request
                HttpWebResponse response = (HttpWebResponse)
                    request.GetResponse();

                // we will read data via the response stream
                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    // fill the buffer with data
                    count = resStream.Read(buf, 0, buf.Length);

                    // make sure we read some data
                    if (count != 0)
                    {
                        // translate from bytes to ASCII text
                        tempString = Encoding.ASCII.GetString(buf, 0, count);

                        // continue building the string
                        sb.Append(tempString);
                    }
                }
                while (count > 0); // any more data to read?
                string __data = sb.ToString();
                return __data;
            }
            catch (Exception err)
            {
                ErrorHandler.HandleError("Error Occurred In RefreshFromService", err);
            }
            return null;

        }
        public List<Project> GetProjects()
        {
            try
            {
                if (PasswordSet())
                {
                    string __data = GetWebData(GetAllProjectsUrl());
                    __data = __data.Substring(1, __data.Length - 2);
                    string[] __rows = __data.Split(new string[] { "}, {" } , StringSplitOptions.None);
                    List<Project> __list = new List<Project>();
                    foreach (string __row in __rows)
                    {
                        Regex __reg = null;
                        Match __match = null;
                        Project __p = new Project();
                        //Get Name
                        __reg = new Regex("\"name\":\\s+\"*(|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Name = __val;
                        }

                        //Get ID
                        __reg = new Regex("\"id\":\\s+\\d+");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.ID = long.Parse(__val);
                        }
                        //Get Color
                        __reg = new Regex("\"color\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Color = ColorTranslator.FromHtml(__val);
                        }

                        __reg = new Regex("\"user_id\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.UserID = int.Parse(__val);
                        }

                        __reg = new Regex("\"collapsed\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            if (__val == "0")
                                __p.Collapsed = false;
                            else
                                __p.Collapsed = true;
                        }
                        __reg = new Regex("\"item_order\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Order = int.Parse(__val);
                        }
                        __reg = new Regex("\"cache_count\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.CacheCount = int.Parse(__val);
                        }
                        __reg = new Regex("\"indent\":\\s+\"*(#|\\w|\\s)+\"*,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Indent = int.Parse(__val);
                        }
                        if (__p.Indent > 0)
                        {
                            for (int i = 1; i < __p.Indent; i++)
                            {
                                __p.Name = "--" + __p.Name;
                            }
                        }
                        __list.Add(__p);
                    }
                    return __list;
                }
                return null;
            }
            catch (Exception err)
            {
                ErrorHandler.HandleError("Error Occurred In RefreshFromService", err);
            }
            return null;
        }
        public List<TaskItem> GetCompletedItems(long projectid)
        {
            try
            {
                if (PasswordSet())
                {
                    string __data = GetWebData(GetCompletedItemsUrl(projectid));
                    __data = __data.Substring(1, __data.Length - 2);
                    string[] __rows = __data.Split(new string[] { "}, {" } , StringSplitOptions.None);
                    List<TaskItem> __list = new List<TaskItem>();
                    foreach (string __row in __rows)
                    {
                        Regex __reg = null;
                        Match __match = null;
                        TaskItem __p = new TaskItem();
                        //Get Content
                        __reg = new Regex("\"content\":\\s+\"[^\"]*\",");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Content = __val;
                        }
                        __reg = new Regex("\"id\":\\s+\\d+");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.ID = long.Parse(__val);
                        }

                        //Get priority
                        __reg = new Regex("\"priority\":\\s+\\d+,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Priority = int.Parse(__val);
                        }
                        __p.Completed = true;
                        __list.Add(__p);
                    }
                    return __list;
                }
                return null;
            }
            catch (Exception err)
            {
                ErrorHandler.HandleError("Error Occurred In RefreshFromService", err);
            }
            return null;
        }
        public List<TaskItem> GetUncompletedItems(long projectid)
        {
            try
            {
                if (PasswordSet())
                {
                    string __data = GetWebData(GetUncompletedItemsUrl(projectid));
                    __data = __data.Substring(1, __data.Length - 2);
                    string[] __rows = __data.Split(new string[] { "}, {" } , StringSplitOptions.None);
                    List<TaskItem> __list = new List<TaskItem>();
                    foreach (string __row in __rows)
                    {
                        Regex __reg = null;
                        Match __match = null;
                        TaskItem __p = new TaskItem();
                        //Get Content
                        __reg = new Regex("\"content\":\\s+\"[^\"]*\",");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Content = __val;
                        }
                        __reg = new Regex("\"id\":\\s+\\d+");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.ID = long.Parse(__val);
                        }
                        //Get priority
                        __reg = new Regex("\"priority\":\\s+\\d+,");
                        __match = __reg.Match(__row);
                        if (__match.Success)
                        {
                            string __val = __row.Substring(__match.Index, __match.Length);
                            __val = CleanupData(__val.Substring(__val.IndexOf(":") + 1));
                            __p.Priority = int.Parse(__val);
                        }
                        __p.Completed = false;
                        __list.Add(__p);
                    }
                    return __list;
                }
                return null;
            }
            catch (Exception err)
            {
                ErrorHandler.HandleError("Error Occurred In RefreshFromService", err);
            }
            return null;
        }

        private Uri GetAllProjectsUrl()
        {
            return new Uri(todobaseurl + getallprojects.Replace("[TOKEN]", password));
        }

        private Uri GetUncompletedItemsUrl(long projid)
        {
            return new Uri(todobaseurl + getuncompleteditems.Replace("[TOKEN]", password).Replace("[PROJID]",projid.ToString()));
        }
        private Uri GetCompletedItemsUrl(long projid)
        {
            return new Uri(todobaseurl + getcompleteditems.Replace("[TOKEN]", password).Replace("[PROJID]", projid.ToString()));
        }
        private Uri GetAddItemUrl(long projid,string content,int priority)
        {
            return new Uri(todobaseurl + additem.Replace("[CONTENT]",content).Replace("[TOKEN]", password).Replace("[PROJID]", projid.ToString()).Replace("[PRIORITY]",priority.ToString()));
        }
        private Uri GetUpdateItemUrl(long id, string content, int priority)
        {
            return new Uri(todobaseurl + updateitem.Replace("[CONTENT]", content).Replace("[TOKEN]", password).Replace("[ID]", id.ToString()).Replace("[PRIORITY]", priority.ToString()));
        }
        private Uri GetDeleteItemUrl(long id)
        {
            return new Uri(todobaseurl + deleteitem.Replace("[TOKEN]", password).Replace("[ID]", id.ToString()));
        }
        private Uri GetUpdateCompletedUrl(long id, bool completed)
        {
            return new Uri(todobaseurl + updatecompleted.Replace("[IDS]", id.ToString()).Replace("[TOKEN]", password).ToString());
        }

        private bool PasswordSet()
        {
            return password != string.Empty;
        }

        private string CleanupData(string data)
        {
            string __tmp = data.Trim();
            if (__tmp.EndsWith(","))
                __tmp = __tmp.Substring(0, __tmp.Length - 1);
            if (__tmp.StartsWith("\""))
                __tmp = __tmp.Substring(1, __tmp.Length - 1);
            if (__tmp.EndsWith("\""))
                __tmp = __tmp.Substring(0, __tmp.Length - 1);
            if(__tmp.EndsWith("}"))
                __tmp = __tmp.Substring(0, __tmp.Length - 1);
            
            return __tmp;
        }

        public void AddItem(long projectid, string data, DateTime date,int priority)
        {
            if (PasswordSet())
            {
                string __data = GetWebData(GetAddItemUrl(projectid,data,priority));
                Console.Write(__data);
            }
        }
        public void UpdateItem(long id, string data, DateTime date, int priority)
        {
            if (PasswordSet())
            {
                string __data = GetWebData(GetUpdateItemUrl(id, data, priority));
                Console.Write(__data);
            }
        }
        public void DeleteItem(long id)
        {
            if (PasswordSet())
            {
                string __data = GetWebData(GetDeleteItemUrl(id));
                Console.Write(__data);
            }
        }
        public void UpdateItemChecked(long id, bool completed)
        {
            if (PasswordSet())
            {
                string __data = GetWebData(GetUpdateCompletedUrl(id,completed));
                Console.Write(__data);
            }
        }
    }


    class ErrorHandler
    {
        public static void HandleError(string friendlymessage,Exception err)
        {
            MessageBox.Show(friendlymessage + Environment.NewLine + Environment.NewLine + err.ToString(), "An Error Occurred", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}
